一文彻底搞懂序列化和反序列化

您所在的位置:网站首页 序列化 反序列化 一文彻底搞懂序列化和反序列化

一文彻底搞懂序列化和反序列化

2024-03-21 03:23| 来源: 网络整理| 查看: 265

目录 背景步骤概念序列化(Serialization)反序列化(Deserialization)使用场景理解原理小Demo(可以理解成编码解码,很简单的)使用redis步骤简单介绍redis 总结

背景

最近项目中要按照对象方式进行存取,使用时再拿出来,于是我们就要学习序列化和反序列化的相关知识。

基于我们的项目,按照课表进行推课的时候,课表中当前课程结束的时候,将执行的颗粒存到redis中。

序列化是将对象转换为字节流的一种方式,与之对应的是反序列化,将二进制流转为对象的一种形式。 由于序列化会将对象的状态信息转换为字节流,这样就可以将对象写入文件,保存到数据库或者是进行网络传输发送到另外一个系统,这样可以达即使在不同的环境或者系统重,只要可以读取这些字节流就可以构建出与初始对象状态完全相同的对象。 在项目中我显式使用序列化的方式是我在后端controller返回实体类都实现了 Serializable 接口,这样就可以实现正常的网络传输,http协议是基于文本传输的,所以我后端想要往前端传数据,就要将对象转换为文本格式(JSON 或者 XML)才能发给前端,前端才能识别,这个过程就涉及到了序列化。还有一个应用场景是我们在推课过程中,当课暂停的时候,我们需要记录好当前暂停的颗粒位置,并将其存到redis中,这里也是涉及到一个序列化的问题,将内存的颗粒对象通过序列化以后转为json存到redis中,下次继续推这个课的时候再通过反序列化的方式从库里边拿出对应的颗粒。

当我在真正使用的时候可以直接让当前实体类去实现Serializable 接口,当我想只序列化某个字段的时候可以使用 @JsonSerialize 注解 ,注解后可以添加参数指定序列化的格式,或者我不想序列化某个字段的时候使用@JSONField(serialize = false) 注解。

步骤 概念

序列化和反序列化是计算机科学中用于数据存储和传输的重要概念。

序列化(Serialization)

是将数据结构或对象转换成一种可存储或可传输格式的过程。在序列化后,数据可以被写入文件、发送到网络或存储在数据库中,以便在需要时可以再次还原成原始的数据结构或对象。序列化的过程通常涉及将数据转换成字节流或类似的格式,使其能够在不同平台和编程语言之间进行传输和交换。

反序列化(Deserialization)

是序列化的逆过程,即将序列化后的数据重新还原成原始的数据结构或对象。反序列化是从文件、网络数据或数据库中读取序列化的数据,并将其转换回原始形式,以便在程序中进行使用和操作。

使用场景

序列化和反序列化在许多场景中都非常有用,例如:

数据存储:将程序中的数据保存到文件或数据库中,以便在以后重新加载和使用。 网络通信:在网络上传输数据时,需要将数据序列化为字节流,以便在接收端进行反序列化。 分布式系统:在分布式系统中,不同计算节点之间需要通过序列化和反序列化来交换数据。 进程间通信:不同进程之间通信时,数据需要在序列化和反序列化之间进行转换。 常见的序列化格式包括 JSON(JavaScript Object Notation)、XML(eXtensible Markup Language)、Protocol Buffers、MessagePack等。每种格式有其优势和适用场景,选择合适的序列化格式取决于具体的应用需求。

理解原理小Demo(可以理解成编码解码,很简单的) import java.io.*; public class Serialization { private static final File SAVE_FILE = new File("D:" + File.separator + "demo.Class"); public static void saveObject(Object object) throws IOException { ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(SAVE_FILE)); oos.writeObject(object); // 序列化 oos.close(); } public static Object loadObject() throws Exception { ObjectInputStream ois = new ObjectInputStream(new FileInputStream(SAVE_FILE)); Object obj = ois.readObject(); // 反序列化 ois.close(); return obj; } public static void main(String[] args) throws Exception { saveObject(new Class(new Person("p",11),"class",12));// 序列化 Class c = (Class)loadObject(); System.out.println(c); // 反序列化 } public static class Person implements Serializable { private String name; private int age; public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public Person(String name, int age) { this.name = name; this.age = age; } @Override public String toString() { return "Person{" + "name='" + name + '\'' + ", age=" + age + '}'; } } public static class Class implements Serializable{ private Person person; private String name; private int age; public Person getPerson() { return person; } public void setPerson(Person person) { this.person = person; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } @Override public String toString() { return "Class{" + "person=" + person + ", name='" + name + '\'' + ", age=" + age + '}'; } public Class(Person person) { this.person = person; } public Class(Person person, String name, int age) { this.person = person; this.name = name; this.age = age; } } }

可以通过打断点的方式查看对象的展示情况

将内存中的对象通过序列化的方式存储到本地的某个文件中 在这里插入图片描述

然后调用另外一个方法从本地文件中拿到对象放置到内存中

在这里插入图片描述

这样我们就了解了序列化和反序列的概念,下面看看在redis是如何实现序列化和反序列化的吧。

使用redis步骤

建立springboot项目 引入坐标

org.springframework.boot spring-boot-starter-data-redis

建类

在这里插入图片描述

在这里插入代码片 package com.example.redis.config; import com.fasterxml.jackson.annotation.JsonAutoDetect; import com.fasterxml.jackson.annotation.PropertyAccessor; import com.fasterxml.jackson.databind.ObjectMapper; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer; import org.springframework.data.redis.serializer.RedisSerializer; import org.springframework.data.redis.serializer.StringRedisSerializer; @Configuration public class RedisConfig { /** * RedisTemplate配置 */ @Bean public RedisTemplate redisTemplate(LettuceConnectionFactory lettuceConnectionFactory) { // 设置序列化 Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class); ObjectMapper om = new ObjectMapper(); om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY); om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL); jackson2JsonRedisSerializer.setObjectMapper(om); // 配置redisTemplate RedisTemplate redisTemplate = new RedisTemplate(); redisTemplate.setConnectionFactory(lettuceConnectionFactory); RedisSerializer stringSerializer = new StringRedisSerializer(); // key序列化 redisTemplate.setKeySerializer(stringSerializer); // value序列化 redisTemplate.setValueSerializer(jackson2JsonRedisSerializer); // Hash key序列化 redisTemplate.setHashKeySerializer(stringSerializer); // Hash value序列化 redisTemplate.setHashValueSerializer(jackson2JsonRedisSerializer); redisTemplate.afterPropertiesSet(); return redisTemplate; } } server: port: 8081 spring: redis: host: **redis.***d.tech port: 6379 password: *** database: 0 timeout: 300000ms #连接超时 jedis: pool: max-active: 8 #连接池最大的连接数 max-wait: -1ms #连接池最大的阻塞等待时间(负值表示没有限制) max-idle: 500 #连接池最大的空闲连接 package com.example.redis.Entity; import lombok.Data; import java.io.Serializable; import java.util.Date; @Data public class UserInfo implements Serializable { /** * id */ private Integer id; /** * 姓名 */ private String name; /** * 创建时间 */ private Date createTime; } package com.example.redis.utils; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.stereotype.Component; import org.springframework.util.StringUtils; /** * @ClassName RedisUtils * @Description * @Author Lizhou * @Date 2020-10-22 10:10:10 **/ @Slf4j @Component public class RedisUtils { @Autowired private RedisTemplate redisTemplate; /** * 根据key读取数据 */ public Object get(final String key) { if (StringUtils.isEmpty(key)) { return null; } try { return redisTemplate.opsForValue().get(key); } catch (Exception e) { e.printStackTrace(); } return null; } /** * 写入数据 */ public boolean set(final String key, Object value) { if (StringUtils.isEmpty(key)) { return false; } try { redisTemplate.opsForValue().set(key, value); log.info("存入redis成功,key:{},value:{}", key, value); return true; } catch (Exception e) { log.error("存入redis失败,key:{},value:{}", key, value); e.printStackTrace(); } return false; } } package com.example.redis; import com.example.redis.Entity.UserInfo; import com.example.redis.utils.RedisUtils; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import java.util.Date; @SpringBootTest class RedisTestApplicationTests { @Autowired private RedisUtils redisUtil; @Test void contextLoads() { UserInfo userInfo = new UserInfo(); userInfo.setId(1); userInfo.setName("jack"); userInfo.setCreateTime(new Date()); // 放入redis redisUtil.set("user", userInfo); // 从redis中获取 System.out.println("获取到数据:" + redisUtil.get("user")); } }

在这里插入图片描述 根据key值查看redis中的值 在这里插入图片描述

简单介绍redis

Redis(Remote Dictionary Server)是一种开源的高性能键值存储数据库,它也被称为数据结构服务器,因为它支持多种灵活的数据结构。Redis以内存中的数据结构为基础,提供了快速、高效的数据存储和访问能力。它可以用作数据库、缓存、消息代理和排行榜等多种用途。

以下是 Redis 的一些主要特点:

键值存储: Redis将数据存储为键值对,其中键是唯一的标识符,而值可以是字符串、哈希、列表、集合、有序集合等各种数据结构。

内存数据库:(因为我们是面向对象开发,所有就要使用内存数据库啦,因为要把对象存取来哦) Redis的所有数据都存储在内存中,因此具有非常快的读写速度。但是,它也支持将数据持久化到磁盘,以便在重启后恢复数据。

丰富的数据结构: Redis支持多种数据结构,如字符串、哈希表、列表(链表)、集合、有序集合等。这使得Redis在处理不同类型的数据时非常灵活和高效。

高性能: 由于数据存储在内存中,Redis能够实现非常高的读写速度。此外,它使用单线程模型来避免了多线程带来的竞争条件,使得其在单核系统上也能表现出色。

支持事务: Redis支持简单的事务,你可以将多个命令放在一个事务中,然后一次性执行这些命令。在事务执行期间,其他客户端不会对其进行干扰。

发布/订阅: Redis支持发布/订阅模式,允许客户端订阅一个或多个频道,当有消息发布到这些频道时,订阅的客户端将会收到相应的消息。

集群支持: Redis支持将数据分布在多个节点上,从而实现高可用性和横向扩展。

轻量级: Redis的代码库相对较小,没有复杂的依赖,因此非常轻量级且易于安装和部署。

Redis广泛应用于Web开发、缓存、会话存储、实时分析、消息队列等场景。由于其高性能和灵活性,Redis成为了许多应用架构中不可或缺的一部分。

总结

序列化在Redis中发挥着重要的作用,它使得数据可以被转换成一种便于存储和传输的格式,并可以通过网络进行传输。当数据需要被存储到Redis中时,通常需要先进行序列化,将数据转换成适合Redis存储的形式。而在从Redis中取出数据时,则需要进行反序列化,将序列化后的数据重新还原成原始的数据结构,以便在程序中进行使用和操作。

总之,序列化和反序列化是数据在存储和传输过程中的桥梁,而Redis作为高性能的键值存储数据库,则利用序列化机制来存储和操作数据,提供快速、灵活的数据存储和访问服务。通过将数据序列化后存储在Redis中,我们可以充分发挥Redis的优势,实现高效的数据处理和管理。



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3